﻿// -------------------------------------------------------------------------------------------------------
// LICENSE INFORMATION
//
// - This software is licensed under the MIT shared source license.
// - The "official" source code for this project is maintained at http://mtcagent.codeplex.com
//
// Copyright (c) 2010 OpenNETCF Consulting
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
// associated documentation files (the "Software"), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial 
// portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
// -------------------------------------------------------------------------------------------------------

using System;
using System.Reflection;
using System.Threading;

namespace OpenNETCF.MTConnect
{
    internal class PropertyHost
    {
        public IHostedAdapter Adapter { get; set; }
        public DataItem DataItem { get; set; }

        private bool m_shutDown = false;
        private PropertyInfo m_propertyInfo;

        public PropertyHost()
        {
        }

        ~PropertyHost()
        {
            m_shutDown = true;
        }

        public PropertyInfo PropertyInfo 
        {
            get { return m_propertyInfo; }
            set
            {
                m_propertyInfo = value;
                DataItem.ValueType = m_propertyInfo.PropertyType;

                ThreadStart start;
                switch (PropertyInfo.PropertyType.Name.ToLower())
                {
                    case "string":
                        start = WatcherProc<string>;
                        break;
                    case "double":
                        start = WatcherProc<double>;
                        break;
                    case "boolean":
                        start = WatcherProc<bool>;
                        break;
                    case "int32":
                        start = WatcherProc<int>;
                        break;
                    default:
                        throw new NotSupportedException();
                }
                new Thread(start)
                {
                    IsBackground = true,
                    Name = string.Format("PropertyHost[{0}]", PropertyInfo.Name)
                }
                .Start();
            }
        }

        private void WatcherProc<T>()
        {
            Thread.Sleep(5000);

            lock (PropertyInfo)
            {
                T lastValue = default(T);

                while (!m_shutDown)
                {
                    T value = (T)PropertyInfo.GetValue(Adapter, null);

                    if (!value.Equals(lastValue))
                    {
                        DataItem.SetValue(value.ToString());
                        lastValue = value;
                    }

                    Thread.Sleep(1000);
                }
            }
        }

        public void SetProperty(string value)
        {
            if (!DataItem.Writable) return;

            // first get the value to the proper type
            object setValue;

            switch (PropertyInfo.PropertyType.Name.ToLower())
            {
                case "string":
                    setValue = value;
                    break;
                case "double":
                    setValue = double.Parse(value);
                    break;
                case "boolean":
                    setValue = bool.Parse(value);
                    break;
                case "int32":
                    setValue = int.Parse(value);
                    break;
                default:
                    throw new NotSupportedException();
            }

            PropertyInfo.SetValue(Adapter, setValue, null);
        }

    }
}
